package com.ruicar.afs.cloud.common.mq.rabbit.listener;

import org.objectweb.asm.*;

public class ListenerFactory extends ClassLoader implements Opcodes {
    private static int index = 0;
    private static String LISTENER_NAME = "AfsRabbitMqListener";
    private static ListenerFactory instance;

    public static void init(ClassLoader classLoader) {
        if (instance == null) {
            synchronized (ListenerFactory.class) {
                if (instance == null) {
                    instance = new ListenerFactory(classLoader);
                }
            }
        }
    }

    public ListenerFactory(ClassLoader parent) {
        super(parent);
    }

    public static Class<AfsAbstractListener> makeListener(String serviceAlias, String queueName, String containerFactory) {
        ClassWriter cw = new ClassWriter(0);
        FieldVisitor fv;
        MethodVisitor mv;
        AnnotationVisitor av0;

        cw.visit(52, ACC_PUBLIC + ACC_SUPER, "com/ruicar/afs/cloud/common/mq/rabbit/listener/" + LISTENER_NAME + (index), null, "com/ruicar/afs/cloud/common/mq/rabbit/listener/AfsAbstractListener", null);

        cw.visitSource(LISTENER_NAME + (index) + ".java", null);

        {
            av0 = cw.visitAnnotation("Lorg/springframework/stereotype/Component;", true);
            av0.visit("value", LISTENER_NAME + (index));
            av0.visitEnd();
        }
        {
            mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
            mv.visitCode();
            Label l0 = new Label();
            mv.visitLabel(l0);
            mv.visitLineNumber(9, l0);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKESPECIAL, "com/ruicar/afs/cloud/common/mq/rabbit/listener/AfsAbstractListener", "<init>", "()V", false);
            mv.visitInsn(RETURN);
            Label l1 = new Label();
            mv.visitLabel(l1);
            mv.visitLocalVariable("this", "Lcom/ruicar/afs/cloud/common/mq/rabbit/listener/" + LISTENER_NAME + (index) + ";", null, l0, l1, 0);
            mv.visitMaxs(1, 1);
            mv.visitEnd();
        }
        {
            mv = cw.visitMethod(ACC_PUBLIC, "listener", "(Lcom/rabbitmq/client/Channel;Lorg/springframework/amqp/core/Message;)V", null, null);
            {
                av0 = mv.visitAnnotation("Lorg/springframework/amqp/rabbit/annotation/RabbitListener;", true);
                {
                    AnnotationVisitor av1 = av0.visitArray("queues");
                    av1.visit(null, queueName);
                    av1.visitEnd();
                }
                av0.visit("containerFactory", containerFactory);
                av0.visit("autoStartup", "true");
                av0.visitEnd();
            }
            mv.visitCode();
            Label l0 = new Label();
            mv.visitLabel(l0);
            mv.visitLineNumber(12, l0);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitVarInsn(ALOAD, 1);
            mv.visitVarInsn(ALOAD, 2);
            mv.visitMethodInsn(INVOKEVIRTUAL, "com/ruicar/afs/cloud/common/mq/rabbit/listener/" + LISTENER_NAME + (index), "process", "(Lcom/rabbitmq/client/Channel;Lorg/springframework/amqp/core/Message;)V", false);
            Label l1 = new Label();
            mv.visitLabel(l1);
            mv.visitLineNumber(13, l1);
            mv.visitInsn(RETURN);
            Label l2 = new Label();
            mv.visitLabel(l2);
            mv.visitLocalVariable("this", "Lcom/ruicar/afs/cloud/common/mq/rabbit/listener/" + LISTENER_NAME + (index) + ";", null, l0, l2, 0);
            mv.visitLocalVariable("channel", "Lcom/rabbitmq/client/Channel;", null, l0, l2, 1);
            mv.visitLocalVariable("message", "Lorg/springframework/amqp/core/Message;", null, l0, l2, 2);
            mv.visitMaxs(3, 3);
            mv.visitEnd();
        }
        {
            mv = cw.visitMethod(ACC_PUBLIC, "getServerAlias", "()Ljava/lang/String;", null, null);
            mv.visitCode();
            Label l0 = new Label();
            mv.visitLabel(l0);
            mv.visitLineNumber(17, l0);
            mv.visitLdcInsn(serviceAlias);
            mv.visitInsn(ARETURN);
            Label l1 = new Label();
            mv.visitLabel(l1);
            mv.visitLocalVariable("this", "Lcom/ruicar/afs/cloud/common/mq/rabbit/listener/" + LISTENER_NAME + (index) + ";", null, l0, l1, 0);
            mv.visitMaxs(1, 1);
            mv.visitEnd();
        }
        {
            mv = cw.visitMethod(ACC_PUBLIC, "getQueueName", "()Ljava/lang/String;", null, null);
            mv.visitCode();
            Label l0 = new Label();
            mv.visitLabel(l0);
            mv.visitLineNumber(22, l0);
            mv.visitLdcInsn(queueName);
            mv.visitInsn(ARETURN);
            Label l1 = new Label();
            mv.visitLabel(l1);
            mv.visitLocalVariable("this", "Lcom/ruicar/afs/cloud/common/mq/rabbit/listener/" + LISTENER_NAME + (index) + ";", null, l0, l1, 0);
            mv.visitMaxs(1, 1);
            mv.visitEnd();
        }
        cw.visitEnd();
        Class clazz = instance.defineClass(cw.toByteArray());
        index++;
        return clazz;
    }

    private Class<?> defineClass(byte[] bytes) {

        return this.defineClass("com.ruicar.afs.cloud.common.mq.rabbit.listener." + LISTENER_NAME + (index), bytes, 0, bytes.length);
    }
}
